using System;
using System.Threading;
using System.IO.Ports;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using NetduinoHappyHour.Asynchronous;
using NetduinoHappyHour.Hardware;
using NetduinoHappyHour.Util;
using SecretLabs.NETMF.Hardware.Netduino;
using System.Reflection;


namespace NetduinoHappyHour.Behaviour
{
    public class TestToMeasure : BaseBehaviour, IExecutable
    {
        public void Execute()
        {
            //CalibrateCheckBattery();
            //ushort test = CheckAdress();
            //TestDisplayMessage();
            //TestTransferProvider();
            //TestAsyncDrive();
            //TestConstruction();
            //TestBtm222();
            //TestComReading();
            //TestReadCommandLine();
            TestExceptionHandling();
            while (true)
            {
                Thread.Sleep(1000);
            }
        }

        private void TestExceptionHandling()
        {
            SystemStatus.Instance().AddMessage("Hallo test exception!");
            throw new Exception("Hallo test exception!");
        }

        private void TestReadCommandLine()
        {
            int speed = 115200;
            byte[] baRead = new byte[50];
            string s;
            SerialPort _serialPort = new SerialPort("COM1", speed);
            _serialPort.Open();

            long timeStart;
            long timeStop;
            long timeDelta;

            // read connect string
            s = ReadLine(_serialPort);
            while (true)
            {
                timeStart = System.DateTime.Now.Ticks;
                s = ReadCommandLine(_serialPort);
                timeStop = System.DateTime.Now.Ticks;
                // took 17.000 ticks
                timeDelta = timeStop - timeStart;
            }
        }

        /// <summary>
        /// Reads a line from SerialPort, newline is truncated, empty lines are ignored
        /// Method call is blocking until not empty line followed by newline is read from SerialPort
        /// </summary>
        /// <returns>Data read from SerialPort</returns>
        private String ReadCommandLine(SerialPort port)
        {
            byte[] buffer = new byte[100];
            string s;
            char[] myTrimChars = {'\n','\r'};

            int readCount = 0;
            int totalReadCount = 0;
            int index = 0;

            // ascii representation 10 is \n, 13 is \r
            while (buffer[index] != 10 && buffer[index] != 13)
            {
                readCount = port.BytesToRead;
                if (readCount == 0)
                {
                    System.Threading.Thread.Sleep(2);
                }
                else
                {
                    port.Read(buffer, totalReadCount, readCount);
                    totalReadCount += readCount;
                    index = totalReadCount - 1;
                }
            }

            // drop empty lines by recursive call
            if (totalReadCount == 1)
            {
                return ReadCommandLine(port);
            }
            s = new String(System.Text.UTF8Encoding.UTF8.GetChars(buffer));
            return s.Trim(myTrimChars);
        }

        private void TestComReading()
        {
            int speed = 115200;
            byte[] baRead = new byte[50];
            string s;
            SerialPort _serialPort = new SerialPort("COM1", speed);
            _serialPort.Open();
            long timeStart;
            long timeStop;
            long timeDelta;
            long timeDelta2;
            long timeDelta3;
            long timeDelta4;

            //_serialPort.Read(baRead, 0, baRead.Length);
            //s = new String(System.Text.UTF8Encoding.UTF8.GetChars(baRead));
            s = ReadLine(_serialPort);
            // Teststring to read: "12345678901234567890"
            timeStart = System.DateTime.Now.Ticks;
            _serialPort.Read(baRead, 0, baRead.Length);
            s = new String(System.Text.UTF8Encoding.UTF8.GetChars(baRead));
            timeStop = System.DateTime.Now.Ticks;
            // took 13'000 ticks
            timeDelta = timeStop - timeStart;

            timeStart = System.DateTime.Now.Ticks;
            s = ReadLine(_serialPort);
            timeStop = System.DateTime.Now.Ticks;
            // took 150'000 ticks
            timeDelta2 = timeStop - timeStart;

            timeStart = System.DateTime.Now.Ticks;
            s = ReadLineNew(_serialPort);
            timeStop = System.DateTime.Now.Ticks;
            // took 150'000 ticks
            timeDelta3 = timeStop - timeStart;

            timeStart = System.DateTime.Now.Ticks;
            s = ReadCommandLine(_serialPort);
            timeStop = System.DateTime.Now.Ticks;
            // took 150'000 ticks
            timeDelta4 = timeStop - timeStart;
        }

        /// <summary>
        /// Reads a line from SerialPort, newline is truncated, empty lines are ignored
        /// Method call is blocking until not empty line followed by newline is read from SerialPort
        /// </summary>
        /// <returns>Data read from SerialPort</returns>
        private String ReadLineNew(SerialPort port)
        {
            byte[] buffer = new byte[100];
            int index = 0;

            port.Read(buffer, index, 1);
            // ascii representation 10 is \n, 13 is \r
            while (buffer[index] != 10 && buffer[index] != 13 && port.BytesToRead > 0)
            {
                index++;
                //port.Read(buffer, index, 1);
                buffer[index] = (byte)port.ReadByte();
            }

            // drop empty lines by recursive call
            if (index == 0)
            {
                return ReadLineNew(port);
            }
            return new String(System.Text.UTF8Encoding.UTF8.GetChars(buffer));

        }

        /// <summary>
        /// Reads a line from SerialPort, newline is truncated, empty lines are ignored
        /// Method call is blocking until not empty line followed by newline is read from SerialPort
        /// </summary>
        /// <returns>Data read from SerialPort</returns>
        private String ReadLine(SerialPort port)
        {
            String s = "";
            byte[] buffer = new byte[1];

            port.Read(buffer, 0, buffer.Length);
            // ascii representation 10 is \n, 13 is \r
            while (buffer[0] != 10 && buffer[0] != 13)
            {
                s = String.Concat(s, (char)buffer[0]);
                port.Read(buffer, 0, buffer.Length);
            }

            // drop empty lines by recursive call
            if (s.Length == 0)
            {
                return ReadLine(port);
            }
            return s;
        }

        private void TestBtm222()
        {
            // ATL0   4800
            // ATL1   9600
            // ATL2  19200
            // ATL3  38400
            // ATL4  57600
            // ATL5 115200
            // ATL6 230400
            // ATL7 460800
            int speed = 115200;
            string code = "ATL5";
            SerialPort _serialPort = new SerialPort("COM1", speed);
            _serialPort.Open();
            bool cw = _serialPort.CanWrite;
            String s;
            byte[] baWrite;
            byte[] baRead = new byte[50];

            // read config
            baWrite = System.Text.UTF8Encoding.UTF8.GetBytes("ATL?");
            _serialPort.Write(baWrite, 0, baWrite.Length);
            // write CR
            _serialPort.WriteByte((byte)13);
            _serialPort.Flush();

            _serialPort.Read(baRead, 0, baRead.Length);
            s = new String(System.Text.UTF8Encoding.UTF8.GetChars(baRead));

            _serialPort.Read(baRead, 0, baRead.Length);
            s = new String(System.Text.UTF8Encoding.UTF8.GetChars(baRead));

            _serialPort.Read(baRead, 0, baRead.Length);
            s = new String(System.Text.UTF8Encoding.UTF8.GetChars(baRead));
            
            baWrite = System.Text.UTF8Encoding.UTF8.GetBytes(code);
            _serialPort.Write(baWrite, 0, baWrite.Length);
            _serialPort.WriteByte((byte)13);
            _serialPort.Flush();

            _serialPort.Read(baRead, 0, baRead.Length);
            s = new String(System.Text.UTF8Encoding.UTF8.GetChars(baRead));

            _serialPort.Read(baRead, 0, baRead.Length);
            s = new String(System.Text.UTF8Encoding.UTF8.GetChars(baRead));

            while (true)
            {
                System.Threading.Thread.Sleep(1000);
            }
            _serialPort.Close();

        }

        private void TestConstruction()
        {
            DriveCommandDualAsync drive = new DriveCommandDualAsync(100,100,9);
            drive.Execute();
        }

        private void TestAsyncDrive()
        {
            //StepperSleep.Sleep(false);
            DriveCommandLeft left = new DriveCommandLeft(200, 5);
            DriveCommandRight right = new DriveCommandRight(100, 10);
            ExecuteAsync execLeft = new ExecuteAsync(left);
            ExecuteAsync execRight = new ExecuteAsync(right);
            execLeft.Execute();
            execRight.Execute();
            System.Threading.Thread.Sleep(500);
        }

        private void CalibrateCheckBattery()
        {
            CheckBattery checkBat = new CheckBattery(true);
            while (true)
            {
                checkBat.Execute();
                Thread.Sleep(1000);
            }
        }

        private void TestTransferProvider()
        {
            MicroLiquidCrystal.ILcdTransferProvider gpio = new MicroLiquidCrystal.GpioLcdTransferProvider(Pins.GPIO_PIN_D8, Pins.GPIO_PIN_D9, Pins.GPIO_PIN_D4, Pins.GPIO_PIN_D5, Pins.GPIO_PIN_D6, Pins.GPIO_PIN_D7);
            MicroLiquidCrystal.ILcdTransferProvider i2c = new MicroLiquidCrystal.I2CLcdTransferProvider();
            gpio.Send(1,true,true);
            i2c.Send(1,true,true);
        }

        private void TestDisplayMessage()
        {
            new DisplayMessage("Hallo Salva").Execute();
        }

        public ushort CheckAdress()
        {
            ushort adr = 0x00;
            I2CDevice.Configuration config;
            I2CDevice i2cDev;
            //byte[] writeBuffer = new byte[] { (byte)'a', (byte)'b' };
            //byte[] writeBuffer = new byte[] { (byte)128, (byte)128 };
            byte[] writeBuffer = new byte[] { (byte)128 };
            //writeBuffer[0] |= 0x80;
            //writeBuffer[1] |= 0x80;
            byte[] readBuffer = new byte[2];
            I2CDevice.I2CTransaction[] readTrans;
            I2CDevice.I2CTransaction[] writeTrans;
            int write = 0;
            int read = 0;
            while (true)
            {
                for (; adr < ushort.MaxValue; adr++)
                {
                    config = new I2CDevice.Configuration(adr, 100);
                    i2cDev = new I2CDevice(config);
                    writeTrans = new I2CDevice.I2CTransaction[]
                    {
                        I2CDevice.CreateWriteTransaction(writeBuffer)
                    };
                    readTrans = new I2CDevice.I2CTransaction[]
                    {
                        I2CDevice.CreateReadTransaction(readBuffer)
                    };
                    write = i2cDev.Execute(writeTrans, 1000);
                    read = i2cDev.Execute(readTrans, 1000);
                    if (read != 0)
                    {
                        i2cDev.Dispose();
                        break;
                    }
                    i2cDev.Dispose();
                }
                return adr;
            }
        }
    }
}
